/*****************************
 *@file: HotUpdateComponent
 *@author: 陈吕唐
 *@desc:
 *@date: 2024-02-19	14:49
 *****************************/
import { _decorator, Asset, Button, Component, game, Label, ProgressBar } from 'cc';
import HotUpdate from './HotUpdate';
const { ccclass, property } = _decorator;

@ccclass('HotUpdateComponent')
export class HotUpdateComponent extends Component {
    /****************************************************************************************************************
     *Readonly 常量
     ****************************************************************************************************************/
    /**
     * 热更新失败发送事件
     */
    public static readonly HOT_UPDATE_FAIL = `HOT_UPDATE_FAIL`;

    /**
     * 热更新成功发送事件
     */
    public static readonly HOT_UPDATE_COMPLETE = `HOT_UPDATE_COMPLETE`;

    /**
     * 热更新大版本更新发送事件
     */
    public static readonly HOT_UPDATE_BIG = `HOT_UPDATE_BIG`;
    /****************************************************************************************************************
     *Property 定义变量
     ****************************************************************************************************************/
    /**
     * 实际实现热更新功能的封装类
     */
    private hotUpdate: HotUpdate;
    /***************************************************************
     *PropertyUI 引用的控件
     ***************************************************************/
    @property({ type: Asset, tooltip: `项目Manifest` })
    private projectManifest: Asset = undefined!;

    @property({ group: { name: 'HOT', id: '1' }, type: Label, tooltip: `更新进度文本组件` })
    private updateLabel: Label = undefined!;

    @property({ group: { name: 'HOT', id: '1' }, type: Label, tooltip: `当前版本文本组件` })
    private versionLabel: Label = undefined!;

    @property({ group: { name: 'HOT', id: '1' }, type: ProgressBar, tooltip: `当前更新进度` })
    private progress: ProgressBar = undefined!;

    @property({ type: Button, tooltip: `热更新重试` })
    private retryButton: Button = undefined!;
    /****************************************************************************************************************
     * Lifecycle 生命周期相关方法
     ****************************************************************************************************************/
    protected onLoad(): void {
        this.updateLabel.string = `正在获取版本号`;
        this.retryButton.node.active = false;

        if (!HotUpdate.isHotUpdate()) {
            this.scheduleOnce(() => {
                this.skipUpdate();
            }, 2);
            return;
        }

        this.retryButton.node.on(Button.EventType.CLICK, this.onClickRetry, this);
        let promise = this.getRemoteVersion();
        promise.then(
            (version) => {
                this.updateLabel.string = `获取远程版本:${version}成功,开始检查更新`;
                this.initHotUpdate(this.projectManifest.nativeUrl, version)
            }, (error) => {
                this.updateLabel.string = `获取远程版本号失败，请检查网络设置后重新打开游戏`;
                this.retryButton.node.active = true;
            }
        )
    }
    /****************************************************************************************************************
     * Public 公有方法
     ****************************************************************************************************************/
    /****************************************************************************************************************
     * private 私有方法
     ****************************************************************************************************************/
    private initHotUpdate(nativeUrl: string, remoteVersion) {
        this.hotUpdate = new HotUpdate(nativeUrl, remoteVersion);
        this.hotUpdate.updatingFunc = this.updating.bind(this);
        this.hotUpdate.updateFailFunc = this.checkUpdateFail.bind(this);
        this.hotUpdate.completeFunc = this.checkUpdateComplete.bind(this);
        this.hotUpdate.bigUpdateFunc = this.bigVersionUpdate.bind(this);
        this.hotUpdate.checkUpdate();
    }
    /**
     * 跳过检查更新
     */
    private skipUpdate() {
        this.checkUpdateComplete();
    }
    /**
     * 更新中
     */
    private updating(event: jsb.EventAssetsManager) {
        let p = event.getDownloadedFiles() / event.getTotalFiles();
        if (this.updateLabel) {
            this.updateLabel.string = `当前加载:${event.getMessage()}`;
        }

        if (this.progress) {
            this.progress.progress = p;
        }
    }

    /**
     * 更新失败
     * @param event 
     */
    private checkUpdateFail(event: jsb.EventAssetsManager) {
        if (this.updateLabel) {
            this.updateLabel.string = `更新失败 code:${event.getEventCode()} ${event.getMessage()}\n请联系客服或点击重试按钮`;
        }
        this.retryButton.node.active = true;
        this.node.emit(HotUpdateComponent.HOT_UPDATE_FAIL);
    }
    /**
     * 检测为大版本更新
     */
    private bigVersionUpdate() {
        if (this.updateLabel) {
            this.updateLabel.string = `已是最新版本`;
        }
        this.node.emit(HotUpdateComponent.HOT_UPDATE_BIG);
    }

    /**
     * 检查更新完成,进入游戏
     */
    private checkUpdateComplete() {
        if (this.updateLabel) {
            this.updateLabel.string = `已是最新版本`;
        }
        this.versionLabel.string = this.hotUpdate?.getLocalVersion();
        this.node.emit(HotUpdateComponent.HOT_UPDATE_COMPLETE);
    }
    /****************************************************************************************************************
     * protected 方法
     ****************************************************************************************************************/
    /**
     * 从服务器获得当前版本号
     * @returns 
     */
    protected getRemoteVersion(): Promise<string> {
        //TODO: 继承该类 重写 从服务器获取版本号
        return Promise.resolve(`1.0.0`);
    }

    /**
     * 点击重试
     */
    protected onClickRetry() {
        this.retryButton.node.active = false;
        game.restart();
    }
    /****************************************************************************************************************
     * Property Get && Set 属性的 get && set 函数
     ****************************************************************************************************************/
}


